﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Schema;
using WhiteRepositoryExplorer.Model;

namespace WhiteRepositoryExplorer.Repository
{
    public class XmlRepositoryReader
    {
        private string _xmlPath;
        private List<WhiteControl> _controls;
        private const string TagControls = "Controls";
        private const string TagControl = "Control";
        private const string AttrId = "id";
        private const string AttrProperties = "properties";
        private const string AttrControlType = "controltype";
        private const string AttrDescription = "description";
        private const string AttrImage = "image";

        public void ReadRepository(string xmlPath)
        {
            
            if (!File.Exists(xmlPath)) throw new FileNotFoundException("XML repository file not found");
            _xmlPath = xmlPath;
            // load xml
            var doc = new XmlDocument();
            doc.Load(_xmlPath);
            // checking if correct XML, otherwize throwing an exception
            if (doc.GetElementsByTagName(TagControls).Count == 0 || doc.GetElementsByTagName(TagControl).Count == 0) 
                throw new InvalidDataException("XML repository has wrong format");

            var controlsList = new List<WhiteControl>();



            for (int i = 0; i < doc.GetElementsByTagName(TagControl).Count; i++)
            {
                XmlNode nodeTemp = doc.GetElementsByTagName(TagControl)[i];
                string id = nodeTemp.Attributes[AttrId].Value;
                string propertiesString = nodeTemp.Attributes[AttrProperties].Value;
                WhiteControlProperties properties = null;
                if (!string.IsNullOrEmpty(propertiesString)) properties = BuildProperty(propertiesString);
                string controltype = nodeTemp.Attributes[AttrControlType].Value;
                string description = nodeTemp.Attributes[AttrDescription] == null ? string.Empty : nodeTemp.Attributes[AttrDescription].Value;
                string image = nodeTemp.Attributes[AttrImage] == null ? string.Empty : nodeTemp.Attributes[AttrImage].Value;

                var whiteControlTemp = new WhiteControl(id, properties, controltype, i + 1, description, image);
                controlsList.Add(whiteControlTemp);
            }

            _controls = controlsList;
        }

        private WhiteControlProperties BuildProperty(string properties)
        {
            string[] tokens = properties.Split('|');

            string automationId = string.Empty;
            string name = string.Empty;
            string className = string.Empty;
            string index = string.Empty;
            string processId = string.Empty;
            string localizedControlType = string.Empty;
            string frameworkId = string.Empty;
            string helpText = string.Empty;

            foreach (var token in tokens)
            {
                Match match = Regex.Match(token, @"(.+)=(.+)");
                string property = match.Groups[1].Value;
                string value = match.Groups[2].Value;

                switch (property.ToLower())
                {
                    case "automationid":
                        automationId = value;
                        break;
                    case "name":
                        name = value;
                        break;
                    case "classname":
                        className = value;
                        break;
                    case "index":
                        index = value;
                        break;
                    case "processid":
                        processId = value;
                        break;
                    case "localizedcontroltype":
                        localizedControlType = value;
                        break;
                    case "frameworkid":
                        frameworkId = value;
                        break;
                    case "helptext":
                        helpText = value;
                        break;
                }
            }

            return new WhiteControlProperties(automationId, name, className, index, processId, localizedControlType, frameworkId, helpText);
        }

        public List<WhiteControl> Controls
        {
            get { return _controls; }
        }

        public List<WhiteControl> Filter(string filter)
        {
            if (_controls == null) return null;
            filter = filter.ToLowerInvariant();
            var listFiltered = new List<WhiteControl>();

            foreach (WhiteControl whiteControl in _controls)
            {
                if (
                whiteControl.ControlType.ToLowerInvariant().Contains(filter) ||
                whiteControl.Id.ToLowerInvariant().Contains(filter) ||
                whiteControl.Description.ToLowerInvariant().Contains(filter) ||
                whiteControl.Properties != null && (
                !string.IsNullOrWhiteSpace(whiteControl.Properties.AutomationId) && whiteControl.Properties.AutomationId.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.ClassName) && whiteControl.Properties.ClassName.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.ProcessId) && whiteControl.Properties.ProcessId.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.FrameworkId) && whiteControl.Properties.FrameworkId.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.Index) && whiteControl.Properties.Index.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.LocalizedControlType) && whiteControl.Properties.LocalizedControlType.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.Name) && whiteControl.Properties.Name.ToLowerInvariant().Contains(filter) ||
                !string.IsNullOrWhiteSpace(whiteControl.Properties.HelpText) && whiteControl.Properties.HelpText.ToLowerInvariant().Contains(filter)
                ))
                {
                    listFiltered.Add(whiteControl);
                }
            }
            return listFiltered;
        }

        public List<WhiteControl> Duplicates()
        {
            var duplicates = new List<WhiteControl>();

            foreach (WhiteControl whiteControl in _controls)
            {
                if (whiteControl.Properties == null) continue;

                foreach (WhiteControl control in _controls.Except(new List<WhiteControl>() {whiteControl}))
                {
                    if (control.Properties == null) continue;

                    if (whiteControl.Properties.AutomationId.Equals(control.Properties.AutomationId))
                    {
                        duplicates.Add(whiteControl);
                        break;
                    }

                    if (!string.IsNullOrWhiteSpace(whiteControl.Properties.Name) &&
                        !string.IsNullOrWhiteSpace(control.Properties.Name) &&
                        whiteControl.Properties.Name.Equals(control.Properties.Name) &&
                        whiteControl.Properties.ClassName.Equals(control.Properties.ClassName) &&
                        whiteControl.ControlType.Equals(control.ControlType))
                    {
                        duplicates.Add(whiteControl);
                        break;
                    }
                }
            }

            return duplicates;
        }
    }
}
